package com.franz.noteapp.compose.editNote

import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.toArgb
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.franz.noteapp.bean.InvalidNoteException
import com.franz.noteapp.bean.NoteBean
import com.franz.noteapp.useCase.NoteUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
 * @param savedStateHandle:可以直接获取导航路由传递的参数，无需在进行特定参数引入
 * Inject注解：此注解可以拿到"Module"声明注解类中所提供的所有对象，例如""NoteUseCase*/
@HiltViewModel
class EditNoteViewModel @Inject constructor(private val noteUseCase: NoteUseCase,savedStateHandle: SavedStateHandle):ViewModel() {

    /**
     * 对标题输入内容进行状态管理
     * text：标题输入框输入的内容
     * hint:标题输入框默认显示内容
     * isHintVisible:标题输入框是否显示hint内容*/
    private val _noteTitle = mutableStateOf(EditNoteTextFieldState(
        hint = "输入笔记标题..."
    ))
    val noteTitle: State<EditNoteTextFieldState> = _noteTitle

    private val _noteContent = mutableStateOf(EditNoteTextFieldState(
        hint = "输入笔记内容..."
    ))
    val noteContent: State<EditNoteTextFieldState> = _noteContent

    /**
     * 对当前笔记的背景颜色进行状态管理
     * 默认是从颜色列表中随机取一个颜色*/
    private val _noteColor = mutableStateOf(NoteBean.noteColor.random().toArgb())
    val noteColor: State<Int> = _noteColor

    /**
     * 对Ui界面的保存笔记事件和笔记内容是否为空事件进行管理
     * 然后将具体内容传递到Ui界面*/
    private val _eventFlow = MutableSharedFlow<EditNoteUiEvent>()
    val eventFlow = _eventFlow.asSharedFlow()

    /**
     * 当前的笔记的id，如果从指定笔记跳转，则此值不为空，若是创建一个新的笔记进行跳转，此值为-1*/
    private var currentId:Int? = null

    /**
     * 对笔记内容进行初始化，从导航路由中获取"noteid"的值，然后在根据此值从数据库中进行查询
     * 若不为空，则刷新当前值(从指定笔记进行路由)
     * 否则，为默认值(创建一个新的笔记)*/
    init {
        savedStateHandle.get<Int>("noteId")?.let { noteId ->
            if (noteId != -1) {
                viewModelScope.launch {
                    noteUseCase.getNote(noteId)?.also { note->
                        currentId = noteId
                        _noteColor.value = note.color
                        _noteTitle.value = noteTitle.value.copy(
                            text = note.title,
                        )
                        _noteContent.value = noteContent.value.copy(
                            text = note.content,
                        )
                    }
                }
            }
        }
    }

    /**
     * 对编辑笔记Ui界面事件进行对应处理
     * 不同的操作会改变某些状态的值，从而刷新页面*/
    fun onEvent(event: EditNoteEvent){
        when(event){
            /**
             * 改变笔记标题的内容
             * 因为采用MVVM模式，笔记Ui界面的标题绑定VM的状态管理变量，然后输入框通过输入字符，并监听输入事件
             * 不断执行此事件，然后在此事件进行VM标题内容改变，笔记Ui界面的标题内容自动刷新*/
            is EditNoteEvent.EnterTitle -> {
                _noteTitle.value = noteTitle.value.copy(
                 text = event.title
                )
            }
            is EditNoteEvent.EnterContent -> {
                _noteContent.value = noteContent.value.copy(
                    text = event.content
                )
            }
            is EditNoteEvent.ChangeColor ->{
                _noteColor.value = event.color
            }
            /**
             * 保存当前笔记内容，将内容插入数据库中
             * 若某一内容为空，触发"InvalidNoteException"异常，则通过"eventFlow"传递到Ui界面，然后通过snack进行显示*/
            is EditNoteEvent.SaveNote ->{
                viewModelScope.launch {
                    try {
                        noteUseCase.insertNote(
                            NoteBean(
                                id = currentId,
                                color = noteColor.value,
                                title = noteTitle.value.text,
                                content = noteContent.value.text,
                                time = System.currentTimeMillis())
                        )
                        _eventFlow.emit(EditNoteUiEvent.SaveNoteUi)
                    }catch (e:InvalidNoteException){
                        _eventFlow.emit(EditNoteUiEvent.ShowSnackBar(e.message ?: "笔记保存失败!"))
                    }
                }
            }
        }
    }
}